package com.st.springts.service;

import com.st.springts.entity.Department;
import com.st.springts.entity.DepartmentDTO;
import com.st.springts.mapper.DepartmentMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class DepartmentService {

    private static final String CACHE_KEY = "department_tree";
    private static final Logger logger = LoggerFactory.getLogger(DepartmentService.class);

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Cacheable(value = "departmentTree", key = "'all'")
    public List<DepartmentDTO> getDepartmentTree() {
        logger.info("Fetching department tree from database...");

        List<Department> allDepartments = departmentMapper.findAll();

        //2.构建树形结构
        List<Department> tree = bulidTree(allDepartments);

        //3.转换为DTO
        List<DepartmentDTO> result = tree.stream().map(DepartmentDTO::fromEntity)
                .collect(Collectors.toList());

        return result;
    }

    public List<DepartmentDTO> getDepartmentTreeWithManualCache(){
        //1.尝试从redis获取缓存
        List<DepartmentDTO> cachedTree = getFromCache();
        if (cachedTree != null) {
            logger.info("Returning department tree from cache");
            return cachedTree;
        }
        logger.info("Cache miss, fetching from database...");

        // 2. 从数据库获取所有部门
        List<Department> allDepartments = departmentMapper.findAll();

        // 3. 构建树形结构
        List<Department> tree = bulidTree(allDepartments);

        // 4. 转换为DTO
        List<DepartmentDTO> result = tree.stream()
                .map(DepartmentDTO::fromEntity)
                .collect(Collectors.toList());

        // 5. 将结果存入缓存
        saveToCache(result);

        return result;
    }

    private List<Department> bulidTree(List<Department> allDepartments) {
        Map<Long, Department> departmentMap = new HashMap<>();
        List<Department> rootDepartments = new ArrayList<>();

        for (Department dept : allDepartments) {
            dept.setChildren(new ArrayList<>());
            departmentMap.put(dept.getId(), dept);
        }

        for (Department dept : allDepartments) {
            if (dept.getParentId() == null) {
                rootDepartments.add(dept);
            }else {
                Department parent = departmentMap.get(dept.getParentId());
                if (parent == null) {
                    parent.getChildren().add(dept);
                }
            }
        }
        return rootDepartments;
    }

    //从缓存获取数据
    private List<DepartmentDTO> getFromCache(){
        try {
            ValueOperations<String, Object> ops = redisTemplate.opsForValue();
            Object cached = ops.get(CACHE_KEY);
            if (cached instanceof List){
                return (List<DepartmentDTO>) cached;
            }
        }catch (Exception e){
            logger.error("Error getting data from Redis cache", e);
        }
               return null;
    }

    private void saveToCache(List<DepartmentDTO> tree) {
        try{
            ValueOperations<String, Object> ops = redisTemplate.opsForValue();
            ops.set(CACHE_KEY, tree,1, TimeUnit.HOURS);
            logger.info("Department tree saved to cache");
        }catch (Exception e){
            logger.error("Error saving data to Redis cache", e);
        }
    }

    //清除缓存（当部门数据变更时调用）
@CacheEvict(value = "departmentTree", key = "'all'")
    public void clearCache() {
        logger.info("Department tree cache cleared");
    }

    public void clearManualCache(){
        try {
            redisTemplate.delete(CACHE_KEY);
            logger.info("Manual department tree cache cleared");
        } catch (Exception e) {
            logger.error("Error clearing Redis cache", e);
        }
    }
//    public List<Department> getDepartmentTree(){
//        List<Department> rootDepartments = departmentMapper.findRootDepartments();
//        for (Department dept : rootDepartments){
//            buildTree(dept);
//        }
//        return rootDepartments;
//    }
//
//    private void buildTree(Department parent){
//        List<Department> children = departmentMapper.findByParentId(parent.getId());
//        if (!children.isEmpty()){
//            parent.setChildren(children);
//            for (Department child : children){
//                buildTree(child);
//            }
//        }
//    }

//    public List<Department> getDepartmentTree(){
//        List<Department> allDepartments = departmentMapper.findAll();
//        return buildTree(allDepartments);
//    }
//
//    private List<Department> buildTree(List<Department> allDepartments){
//        Map<Long, Department> departmentMap = new HashMap<>();
//        List<Department> rootDepartments = new ArrayList<>();
//
//        for (Department dept : allDepartments) {
//            dept.setChildren(new ArrayList<>());
//            departmentMap.put(dept.getId(), dept);
//        }
//
//        for (Department dept : allDepartments) {
//            if (dept.getParentId() == null){
//                rootDepartments.add(dept);
//            }else {
//                Department parent = departmentMap.get(dept.getParentId());
//                if (parent != null){
//                    parent.getChildren().add(dept);
//                }
//            }
//        }
//        return rootDepartments;
//    }
}
